

import { isReadonly } from './utils.js';
const hasOwnProperty$1 = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty$1.call(val, key);
const isObject = (val) => val !== null && typeof val === 'object';
const isArray = Array.isArray;
const isSymbol = (val) => typeof val === 'symbol';
const isString = (val) => typeof val === 'string';
const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
const toRawType = (value) => {
	// 从类似“[object RawType]”的字符串中提取“RawType”
	return toTypeString(value).slice(8, -1);
};
export const toReactive = (value) => isObject(value) ? reactive(value) : value
const readonlyGet = /*#__PURE__*/ createGetter(true);

function warn$1(msg, ...args) {
	console.warn(`[Vue warn] ${msg}`, ...args);
}
const cacheStringFunction = (fn) => {
	const cache = Object.create(null);
	return ((str) => {
		const hit = cache[str];
		return hit || (cache[str] = fn(str));
	});
};
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
function createReadonlyMethod(type) {
	return function (...args) {
		{
			const key = args[0] ? `on key "${args[0]}" ` : ``;
			console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));
		}
		return type === "delete" /* TriggerOpTypes.DELETE */ ? false : this;
	};
}
function createForEach(isReadonly, isShallow) {
	return function forEach(callback, thisArg) {
		const observed = this;
		const target = observed["__v_raw" /* ReactiveFlags.RAW */];
		const rawTarget = toRaw(target);
		const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
		!isReadonly && track(rawTarget, "iterate" /* TrackOpTypes.ITERATE */, ITERATE_KEY);
		return target.forEach((value, key) => {
			// important: make sure the callback is
			// 1. invoked with the reactive map as `this` and 3rd arg
			// 2. the value received should be a corresponding reactive/readonly.
			return callback.call(thisArg, wrap(value), wrap(key), observed);
		});
	};
}
const get$1 = /*#__PURE__*/ createGetter();
const set$1 = /*#__PURE__*/ createSetter();
function has$1(target, key) {
	const result = Reflect.has(target, key);
	if (!isSymbol(key) || !builtInSymbols.has(key)) {
		track(target, "has" /* TrackOpTypes.HAS */, key);
	}
	return result;
}
function deleteProperty(target, key) {
	const hadKey = hasOwn(target, key);
	const oldValue = target[key];
	const result = Reflect.deleteProperty(target, key);
	if (result && hadKey) {
		trigger(target, "delete" /* TriggerOpTypes.DELETE */, key, undefined, oldValue);
	}
	return result;
}
function ownKeys(target) {
	track(target, "iterate" /* TrackOpTypes.ITERATE */, isArray(target) ? 'length' : ITERATE_KEY);
	return Reflect.ownKeys(target);
}
const mutableHandlers = {
	get: get$1,
	set: set$1,
	deleteProperty,
	has: has$1,
	ownKeys
};
const readonlyHandlers = {
	get: readonlyGet,
	set(target, key) {
		{
			warn$1(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
		}
		return true;
	},
	deleteProperty(target, key) {
		{
			warn$1(`Delete operation on key "${String(key)}" failed: target is readonly.`, target);
		}
		return true;
	}
};
function has(key, isReadonly = false) {
	const target = this["__v_raw" /* ReactiveFlags.RAW */];
	const rawTarget = toRaw(target);
	const rawKey = toRaw(key);
	if (!isReadonly) {
		if (key !== rawKey) {
			track(rawTarget, "has" /* TrackOpTypes.HAS */, key);
		}
		track(rawTarget, "has" /* TrackOpTypes.HAS */, rawKey);
	}
	return key === rawKey
		? target.has(key)
		: target.has(key) || target.has(rawKey);
}
function add(value) {
	value = toRaw(value);
	const target = toRaw(this);
	const proto = getProto(target);
	const hadKey = proto.has.call(target, value);
	if (!hadKey) {
		target.add(value);
		trigger(target, "add" /* TriggerOpTypes.ADD */, value, value);
	}
	return this;
}
function set(key, value) {
	value = toRaw(value);
	const target = toRaw(this);
	const { has, get } = getProto(target);
	let hadKey = has.call(target, key);
	if (!hadKey) {
		key = toRaw(key);
		hadKey = has.call(target, key);
	}
	else {
		checkIdentityKeys(target, has, key);
	}
	const oldValue = get.call(target, key);
	target.set(key, value);
	if (!hadKey) {
		trigger(target, "add" /* TriggerOpTypes.ADD */, key, value);
	}
	else if (hasChanged(value, oldValue)) {
		trigger(target, "set" /* TriggerOpTypes.SET */, key, value, oldValue);
	}
	return this;
}
function deleteEntry(key) {
	const target = toRaw(this);
	const { has, get } = getProto(target);
	let hadKey = has.call(target, key);
	if (!hadKey) {
		key = toRaw(key);
		hadKey = has.call(target, key);
	}
	else {
		checkIdentityKeys(target, has, key);
	}
	const oldValue = get ? get.call(target, key) : undefined;
	// forward the operation before queueing reactions
	const result = target.delete(key);
	if (hadKey) {
		trigger(target, "delete" /* TriggerOpTypes.DELETE */, key, undefined, oldValue);
	}
	return result;
}
function clear() {
	const target = toRaw(this);
	const hadItems = target.size !== 0;
	const oldTarget = isMap(target)
		? new Map(target)
		: new Set(target)
		;
	// forward the operation before queueing reactions
	const result = target.clear();
	if (hadItems) {
		trigger(target, "clear" /* TriggerOpTypes.CLEAR */, undefined, undefined, oldTarget);
	}
	return result;
}
function createIterableMethod(method, isReadonly, isShallow) {
	return function (...args) {
		const target = this["__v_raw" /* ReactiveFlags.RAW */];
		const rawTarget = toRaw(target);
		const targetIsMap = isMap(rawTarget);
		const isPair = method === 'entries' || (method === Symbol.iterator && targetIsMap);
		const isKeyOnly = method === 'keys' && targetIsMap;
		const innerIterator = target[method](...args);
		const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
		!isReadonly &&
			track(rawTarget, "iterate" /* TrackOpTypes.ITERATE */, isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);
		// return a wrapped iterator which returns observed versions of the
		// values emitted from the real iterator
		return {
			// iterator protocol
			next() {
				const { value, done } = innerIterator.next();
				return done
					? { value, done }
					: {
						value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
						done
					};
			},
			// iterable protocol
			[Symbol.iterator]() {
				return this;
			}
		};
	};
}
function createInstrumentations() {
	const mutableInstrumentations = {
		get(key) {
			return get(this, key);
		},
		get size() {
			return size(this);
		},
		has,
		add,
		set,
		delete: deleteEntry,
		clear,
		forEach: createForEach(false, false)
	};
	const shallowInstrumentations = {
		get(key) {
			return get(this, key, false, true);
		},
		get size() {
			return size(this);
		},
		has,
		add,
		set,
		delete: deleteEntry,
		clear,
		forEach: createForEach(false, true)
	};
	const readonlyInstrumentations = {
		get(key) {
			return get(this, key, true);
		},
		get size() {
			return size(this, true);
		},
		has(key) {
			return has.call(this, key, true);
		},
		add: createReadonlyMethod("add" /* TriggerOpTypes.ADD */),
		set: createReadonlyMethod("set" /* TriggerOpTypes.SET */),
		delete: createReadonlyMethod("delete" /* TriggerOpTypes.DELETE */),
		clear: createReadonlyMethod("clear" /* TriggerOpTypes.CLEAR */),
		forEach: createForEach(true, false)
	};
	const shallowReadonlyInstrumentations = {
		get(key) {
			return get(this, key, true, true);
		},
		get size() {
			return size(this, true);
		},
		has(key) {
			return has.call(this, key, true);
		},
		add: createReadonlyMethod("add" /* TriggerOpTypes.ADD */),
		set: createReadonlyMethod("set" /* TriggerOpTypes.SET */),
		delete: createReadonlyMethod("delete" /* TriggerOpTypes.DELETE */),
		clear: createReadonlyMethod("clear" /* TriggerOpTypes.CLEAR */),
		forEach: createForEach(true, true)
	};
	const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator];
	iteratorMethods.forEach(method => {
		mutableInstrumentations[method] = createIterableMethod(method, false, false);
		readonlyInstrumentations[method] = createIterableMethod(method, true, false);
		shallowInstrumentations[method] = createIterableMethod(method, false, true);
		shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);
	});
	return [
		mutableInstrumentations,
		readonlyInstrumentations,
		shallowInstrumentations,
		shallowReadonlyInstrumentations
	];
}
const [mutableInstrumentations, readonlyInstrumentations, shallowInstrumentations, shallowReadonlyInstrumentations] = /* #__PURE__*/ createInstrumentations();

function createInstrumentationGetter(isReadonly, shallow) {
	const instrumentations = shallow
		? isReadonly
			? shallowReadonlyInstrumentations
			: shallowInstrumentations
		: isReadonly
			? readonlyInstrumentations
			: mutableInstrumentations;
	return (target, key, receiver) => {
		if (key === "__v_isReactive" /* ReactiveFlags.IS_REACTIVE */) {
			return !isReadonly;
		}
		else if (key === "__v_isReadonly" /* ReactiveFlags.IS_READONLY */) {
			return isReadonly;
		}
		else if (key === "__v_raw" /* ReactiveFlags.RAW */) {
			return target;
		}
		return Reflect.get(hasOwn(instrumentations, key) && key in target
			? instrumentations
			: target, key, receiver);
	};
}
const readonlyCollectionHandlers = {
	get: /*#__PURE__*/ createInstrumentationGetter(true, false)
};
const mutableCollectionHandlers = {
	get: /*#__PURE__*/ createInstrumentationGetter(false, false)
};
/**
 * Creates a readonly copy of the original object. Note the returned copy is not
 * made reactive, but `readonly` can be called on an already reactive object.
 */
function readonly(target) {
	return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
}
/**
   * Make a map and return a function for checking if a key
   * is in that map.
   * IMPORTANT: all calls of this function must be prefixed with
   * \/\*#\_\_PURE\_\_\*\/
   * So that rollup can tree-shake them if necessary.
   */
function makeMap(str, expectsLowerCase) {
	const map = Object.create(null);
	const list = str.split(',');
	for (let i = 0; i < list.length; i++) {
		map[list[i]] = true;
	}
	return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
const isNonTrackableKeys = /*#__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(
	/*#__PURE__*/
	Object.getOwnPropertyNames(Symbol)
		// ios10.x Object.getOwnPropertyNames(Symbol) can enumerate 'arguments' and 'caller'
		// but accessing them on Symbol leads to TypeError because Symbol is a strict mode
		// function
		.filter(key => key !== 'arguments' && key !== 'caller')
		.map(key => Symbol[key])
		.filter(isSymbol));

function targetTypeMap(rawType) {
	switch (rawType) {
		case 'Object':
		case 'Array':
			return 1 /* TargetType.COMMON */;
		case 'Map':
		case 'Set':
		case 'WeakMap':
		case 'WeakSet':
			return 2 /* TargetType.COLLECTION */;
		default:
			return 0 /* TargetType.INVALID */;
	}
}
function getTargetType(value) {
	return value["__v_skip" /* ReactiveFlags.SKIP */] || !Object.isExtensible(value)
		? 0 /* TargetType.INVALID */
		: targetTypeMap(toRawType(value));
}

function createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {
	if (!isObject(target)) {
		{
			console.warn(`value cannot be made reactive: ${String(target)}`);
		}
		return target;
	}
	// 目标已经是一个代理，请将其返回。
	// exception: calling readonly() on a reactive object
	if (target["__v_raw" /* ReactiveFlags.RAW */] &&
		!(isReadonly && target["__v_isReactive" /* ReactiveFlags.IS_REACTIVE */])) {
		return target;
	}
	// 目标已具有相应的代理
	const existingProxy = proxyMap.get(target);
	if (existingProxy) {
		return existingProxy;
	}
	// 只能观察到特定的值类型。
	const targetType = getTargetType(target);
	if (targetType === 0 /* TargetType.INVALID */) {
		return target;
	}
	const proxy = new Proxy(target, targetType === 2 /* TargetType.COLLECTION */ ? collectionHandlers : baseHandlers);
	proxyMap.set(target, proxy);
	return proxy;
}
const targetMap = new WeakMap();
function track(target, type, key) {
	if (shouldTrack && activeEffect) {
		let depsMap = targetMap.get(target);
		if (!depsMap) {
			targetMap.set(target, (depsMap = new Map()));
		}
		let dep = depsMap.get(key);
		if (!dep) {
			depsMap.set(key, (dep = createDep()));
		}
		const eventInfo = { effect: activeEffect, target, type, key }
			;
		trackEffects(dep, eventInfo);
	}
}
const isIntegerKey = (key) => isString(key) &&
	key !== 'NaN' &&
	key[0] !== '-' &&
	'' + parseInt(key, 10) === key;
function createGetter(isReadonly = false, shallow = false) {
	return function get(target, key, receiver) {
		if (key === "__v_isReactive" /* ReactiveFlags.IS_REACTIVE */) {
			return !isReadonly;
		}
		else if (key === "__v_isReadonly" /* ReactiveFlags.IS_READONLY */) {
			return isReadonly;
		}
		else if (key === "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */) {
			return shallow;
		}
		else if (key === "__v_raw" /* ReactiveFlags.RAW */ &&
			receiver ===
			(isReadonly
				? shallow
					? shallowReadonlyMap
					: readonlyMap
				: shallow
					? shallowReactiveMap
					: reactiveMap).get(target)) {
			return target;
		}
		const targetIsArray = isArray(target);
		if (!isReadonly) {
			if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
				return Reflect.get(arrayInstrumentations, key, receiver);
			}
			if (key === 'hasOwnProperty') {
				return hasOwnProperty;
			}
		}
		const res = Reflect.get(target, key, receiver);
		if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
			return res;
		}
		if (!isReadonly) {
			track(target, "get" /* TrackOpTypes.GET */, key);
		}
		if (shallow) {
			return res;
		}
		if (isRef(res)) {
			// ref unwrapping - skip unwrap for Array + integer key.
			return targetIsArray && isIntegerKey(key) ? res : res.value;
		}
		if (isObject(res)) {
			// Convert returned value into a proxy as well. we do the isObject check
			// here to avoid invalid value warning. Also need to lazy access readonly
			// and reactive here to avoid circular dependency.
			return isReadonly ? readonly(res) : reactive(res);
		}
		return res;
	};
}
function createSetter(shallow = false) {
	return function set(target, key, value, receiver) {
		let oldValue = target[key];
		if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
			return false;
		}
		if (!shallow) {
			if (!isShallow(value) && !isReadonly(value)) {
				oldValue = toRaw(oldValue);
				value = toRaw(value);
			}
			if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
				oldValue.value = value;
				return true;
			}
		}
		const hadKey = isArray(target) && isIntegerKey(key)
			? Number(key) < target.length
			: hasOwn(target, key);
		const result = Reflect.set(target, key, value, receiver);
		// don't trigger if target is something up in the prototype chain of original
		if (target === toRaw(receiver)) {
			if (!hadKey) {
				trigger(target, "add" /* TriggerOpTypes.ADD */, key, value);
			}
			else if (hasChanged(value, oldValue)) {
				trigger(target, "set" /* TriggerOpTypes.SET */, key, value, oldValue);
			}
		}
		return result;
	};
}

const reactiveMap = new WeakMap();
export function reactive(target) {
	// 如果试图观察只读代理，则返回只读版本。
	if (isReadonly(target)) {
		return target;
	}
	return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}


function isRef(r) {
	return !!(r && r.__v_isRef === true);
}

function shallowRef(value) {
	return createRef(value, true);
}

const wasTracked = (dep) => (dep.w & trackOpBit) > 0;
const newTracked = (dep) => (dep.n & trackOpBit) > 0;
let activeEffect;
function trackEffects(dep, debuggerEventExtraInfo) {
	let shouldTrack = false;
	if (effectTrackDepth <= maxMarkerBits) {
		if (!newTracked(dep)) {
			dep.n |= trackOpBit; // set newly tracked
			shouldTrack = !wasTracked(dep);
		}
	}
	else {
		// Full cleanup mode.
		shouldTrack = !dep.has(activeEffect);
	}
	if (shouldTrack) {
		dep.add(activeEffect);
		activeEffect.deps.push(dep);
		if (activeEffect.onTrack) {
			activeEffect.onTrack(Object.assign({ effect: activeEffect }, debuggerEventExtraInfo));
		}
	}
}
const createDep = (effects) => {
	const dep = new Set(effects);
	dep.w = 0;
	dep.n = 0;
	return dep;
};
let shouldTrack = true;

